From: kaf24@scramble.cl.cam.ac.uk Date: Sat, 27 Mar 2004 10:20:58 +0000 (+0000) Subject: bitkeeper revision 1.825.3.10 (4065558aPBWky8sW_ub8imsOf_yTwg) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~18253^2~11 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22?a=commitdiff_plain;h=55f9f673af8640f24c98997aa024fdf21ac270a4;p=xen.git bitkeeper revision 1.825.3.10 (4065558aPBWky8sW_ub8imsOf_yTwg) Many files: Cleaned up user-space event-channel handling (now better reflects the underlying abstraction). Also simplified handling of exceptional notifications (now a special case of a normal notification). --- diff --git a/tools/xend/lib/main.py b/tools/xend/lib/main.py index 6cbfa5ad35..4b243b3307 100755 --- a/tools/xend/lib/main.py +++ b/tools/xend/lib/main.py @@ -41,8 +41,7 @@ def daemon_loop(): # Interface via which we receive event notifications from other guest # OSes. This interface also allows us to clear/acknowledge outstanding - # notifications --- successive notifications for the same channel are - # dropped until the first notification is cleared. + # notifications. notifier = xend.utils.notifier() ## @@ -169,56 +168,48 @@ def daemon_loop(): break (idx, type) = notification + if not control_list.has_key(idx): + continue + + (port, rbuf, wbuf, con_if) = control_list[idx] + work_done = False + # If we pick up a disconnect notification then we do any necessary - # cleanup, even if the event channel doesn't belong to us. - # This is intended to prevent the event-channel port space from - # getting clogged with stale connections. - if type == notifier.DISCONNECT: + # cleanup. + if type == notifier.EXCEPTION: ret = xc.evtchn_status(idx) - if ret['status'] == 'interdomain': - notifier.clear(idx, notifier.NORMAL) - notifier.clear(idx, notifier.DISCONNECT) - if control_list.has_key(idx): - (port, rbuf, wbuf, con_if) = control_list[idx] - con_if.close() - del control_list[idx], port, rbuf, wbuf, con_if - elif ret['status'] == 'unbound': - # There's noone to do the closure for us... - xc.evtchn_close(idx) - - # A standard notification: probably means there are messages to - # read or that there is space to write messages. - elif type == notifier.NORMAL and control_list.has_key(idx): - (port, rbuf, wbuf, con_if) = control_list[idx] - work_done = False - - # We clear the notification before doing any work, to avoid - # races. - notifier.clear(idx, notifier.NORMAL) - - # Read incoming requests. Currently assume that request - # message always containb console data. - while port.request_to_read(): - msg = port.read_request() - rbuf.write(msg.get_payload()) - port.write_response(msg) - work_done = True - - # Incoming responses are currently thrown on the floor. - while port.response_to_read(): - msg = port.read_response() - work_done = True - - # Send as much pending console data as there is room for. - while not wbuf.empty() and port.space_to_write_request(): - msg = xend.utils.message(0, 0, 0) - msg.append_payload(wbuf.read(msg.MAX_PAYLOAD)) - port.write_request(msg) - work_done = True - - # Finally, notify the remote end of any work that we did. - if work_done: - port.notify() + if ret['status'] == 'unbound': + notifier.unbind(idx) + con_if.close() + del control_list[idx], port, rbuf, wbuf, con_if + continue + + # Read incoming requests. Currently assume that request + # message always containb console data. + while port.request_to_read(): + msg = port.read_request() + rbuf.write(msg.get_payload()) + port.write_response(msg) + work_done = True + + # Incoming responses are currently thrown on the floor. + while port.response_to_read(): + msg = port.read_response() + work_done = True + + # Send as much pending console data as there is room for. + while not wbuf.empty() and port.space_to_write_request(): + msg = xend.utils.message(0, 0, 0) + msg.append_payload(wbuf.read(msg.MAX_PAYLOAD)) + port.write_request(msg) + work_done = True + + # Finally, notify the remote end of any work that we did. + if work_done: + port.notify() + + # Unmask notifications for this port. + notifier.unmask(idx) diff --git a/tools/xend/lib/manager.py b/tools/xend/lib/manager.py index 092caa02fc..8e336763f1 100644 --- a/tools/xend/lib/manager.py +++ b/tools/xend/lib/manager.py @@ -14,10 +14,9 @@ import xend.console, xend.main, xend.utils ## automatically allocated. ## def new_control_interface(dom, console_port=-1): - # Allocate an event channel. Clear pending notifications. + # Allocate an event channel and binbd to it. port = xend.utils.port(dom) - xend.main.notifier.clear(port.local_port, xend.main.notifier.NORMAL) - xend.main.notifier.clear(port.local_port, xend.main.notifier.DISCONNECT) + xend.main.notifier.bind(port.local_port) # If necessary, compute a suitable TCP port for console I/O. if console_port < 0: diff --git a/tools/xend/lib/utils.c b/tools/xend/lib/utils.c index e57b7ed9d3..6a531da0cc 100644 --- a/tools/xend/lib/utils.c +++ b/tools/xend/lib/utils.c @@ -33,9 +33,15 @@ #define EVTCHN_DEV_MAJOR 10 #define EVTCHN_DEV_MINOR 200 #define PORT_NORMAL 0x0000 /* A standard event notification. */ -#define PORT_DISCONNECT 0x8000 /* A port-disconnect notification. */ +#define PORT_EXCEPTION 0x8000 /* An exceptional notification. */ #define PORTIDX_MASK 0x7fff /* Strip subtype to obtain port index. */ -#define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */ +/* /dev/xen/evtchn ioctls: */ +/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */ +#define EVTCHN_RESET _IO('E', 1) +/* EVTCHN_BIND: Bind to teh specified event-channel port. */ +#define EVTCHN_BIND _IO('E', 2) +/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */ +#define EVTCHN_UNBIND _IO('E', 3) /* Size of a machine page frame. */ #define PAGE_SIZE 4096 @@ -76,23 +82,53 @@ static PyObject *xu_notifier_read(PyObject *self, PyObject *args) return Py_None; } -static PyObject *xu_notifier_clear(PyObject *self, PyObject *args) +static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args) { xu_notifier_object *xun = (xu_notifier_object *)self; u16 v; - int idx, type; + int idx; - if ( !PyArg_ParseTuple(args, "ii", &idx, &type) ) + if ( !PyArg_ParseTuple(args, "i", &idx) ) return NULL; - - v = (u16)idx | (u16)type; + v = (u16)idx; + (void)write(xun->evtchn_fd, &v, sizeof(v)); Py_INCREF(Py_None); return Py_None; } +static PyObject *xu_notifier_bind(PyObject *self, PyObject *args) +{ + xu_notifier_object *xun = (xu_notifier_object *)self; + int idx; + + if ( !PyArg_ParseTuple(args, "i", &idx) ) + return NULL; + + if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 ) + return PyErr_SetFromErrno(PyExc_IOError); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args) +{ + xu_notifier_object *xun = (xu_notifier_object *)self; + int idx; + + if ( !PyArg_ParseTuple(args, "i", &idx) ) + return NULL; + + if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 ) + return PyErr_SetFromErrno(PyExc_IOError); + + Py_INCREF(Py_None); + return Py_None; +} + static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args) { xu_notifier_object *xun = (xu_notifier_object *)self; @@ -105,10 +141,20 @@ static PyMethodDef xu_notifier_methods[] = { METH_VARARGS, "Read a (@port, @type) pair.\n" }, - { "clear", - (PyCFunction)xu_notifier_clear, + { "unmask", + (PyCFunction)xu_notifier_unmask, + METH_VARARGS, + "Unmask notifications for a @port.\n" }, + + { "bind", + (PyCFunction)xu_notifier_bind, + METH_VARARGS, + "Get notifications for a @port.\n" }, + + { "unbind", + (PyCFunction)xu_notifier_unbind, METH_VARARGS, - "Clear a (@port, @type) pair.\n" }, + "No longer get notifications for a @port.\n" }, { "fileno", (PyCFunction)xu_notifier_fileno, @@ -147,8 +193,8 @@ static PyObject *xu_notifier_new(PyObject *self, PyObject *args) static PyObject *xu_notifier_getattr(PyObject *obj, char *name) { - if ( strcmp(name, "DISCONNECT") == 0 ) - return PyInt_FromLong(PORT_DISCONNECT); + if ( strcmp(name, "EXCEPTION") == 0 ) + return PyInt_FromLong(PORT_EXCEPTION); if ( strcmp(name, "NORMAL") == 0 ) return PyInt_FromLong(PORT_NORMAL); return Py_FindMethod(xu_notifier_methods, obj, name); diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index d68e28b553..af20f8b533 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -154,11 +154,11 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind) /* * Port 0 is the fallback port for VIRQs that haven't been explicitly - * bound yet. The exception is the 'error VIRQ', which is permanently + * bound yet. The exception is the 'misdirect VIRQ', which is permanently * bound to port 0. */ if ( ((port = p->virq_to_evtchn[virq]) != 0) || - (virq == VIRQ_ERROR) || + (virq == VIRQ_MISDIRECT) || ((port = get_free_port(p)) < 0) ) goto out; @@ -226,7 +226,7 @@ static long __evtchn_close(struct task_struct *p1, int port1) chn1 = p1->event_channel; - /* NB. Port 0 is special (VIRQ_ERROR). Never let it be closed. */ + /* NB. Port 0 is special (VIRQ_MISDIRECT). Never let it be closed. */ if ( (port1 <= 0) || (port1 >= p1->max_event_channel) ) { rc = -EINVAL; @@ -483,7 +483,7 @@ int init_event_channels(struct task_struct *p) p->max_event_channel = INIT_EVENT_CHANNELS; memset(p->event_channel, 0, INIT_EVENT_CHANNELS * sizeof(event_channel_t)); p->event_channel[0].state = ECS_VIRQ; - p->event_channel[0].u.virq = VIRQ_ERROR; + p->event_channel[0].u.virq = VIRQ_MISDIRECT; return 0; } diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 335baee581..2b27b4b824 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -56,19 +56,19 @@ * Virtual interrupts that a guest OS may receive from the hypervisor. */ -#define VIRQ_BLKDEV 0 /* A block device response has been queued. */ -#define VIRQ_TIMER 1 /* A timeout has been updated. */ -#define VIRQ_DIE 2 /* OS is about to be killed. Clean up please! */ -#define VIRQ_DEBUG 3 /* Request guest to dump debug info (gross!) */ -#define VIRQ_NET 4 /* There are packets for transmission. */ -#define VIRQ_PS2 5 /* PS/2 keyboard or mouse event(s) */ -#define VIRQ_STOP 6 /* Prepare for stopping and possible pickling */ -#define VIRQ_EVTCHN 7 /* Event pending on an event channel */ -#define VIRQ_VBD_UPD 8 /* Event to signal VBDs should be reprobed */ -#define VIRQ_CONSOLE 9 /* This is only for domain-0 initial console. */ -#define VIRQ_PHYSIRQ 10 /* Event to signal pending physical IRQs. */ -#define VIRQ_ERROR 11 /* Catch-all virtual interrupt. */ -#define NR_VIRQS 12 +#define VIRQ_BLKDEV 0 /* A block device response has been queued. */ +#define VIRQ_TIMER 1 /* A timeout has been updated. */ +#define VIRQ_DIE 2 /* OS is about to be killed. Clean up please! */ +#define VIRQ_DEBUG 3 /* Request guest to dump debug info (gross!) */ +#define VIRQ_NET 4 /* There are packets for transmission. */ +#define VIRQ_PS2 5 /* PS/2 keyboard or mouse event(s) */ +#define VIRQ_STOP 6 /* Prepare for stopping and possible pickling */ +#define VIRQ_EVTCHN 7 /* Event pending on an event channel */ +#define VIRQ_VBD_UPD 8 /* Event to signal VBDs should be reprobed */ +#define VIRQ_CONSOLE 9 /* This is only for domain-0 initial console. */ +#define VIRQ_PHYSIRQ 10 /* Event to signal pending physical IRQs. */ +#define VIRQ_MISDIRECT 11 /* Catch-all virtual interrupt. */ +#define NR_VIRQS 12 /* * MMU_XXX: specified in least 2 bits of 'ptr' field. These bits are masked @@ -187,23 +187,22 @@ typedef struct shared_info_st * 2. EXCEPTION -- notifies the domain that there has been some * exceptional event associated with this channel (e.g. remote * disconnect, physical IRQ error). This bit is cleared by the guest. + * A 0->1 transition of this bit will cause the PENDING bit to be set. * 3. MASK -- if this bit is clear then a 0->1 transition of PENDING - * or EXCEPTION will cause an asynchronous upcall to be scheduled. - * This bit is only updated by the guest. It is read-only within Xen. - * If a channel becomes pending or an exceptional event occurs while - * the channel is masked then the 'edge' is lost (i.e., when the - * channel is unmasked, the guest must manually handle pending - * notifications as no upcall will be scheduled by Xen). + * will cause an asynchronous upcall to be scheduled. This bit is only + * updated by the guest. It is read-only within Xen. If a channel + * becomes pending while the channel is masked then the 'edge' is lost + * (i.e., when the channel is unmasked, the guest must manually handle + * pending notifications as no upcall will be scheduled by Xen). * - * To expedite scanning of pending notifications and exceptions, any - * 0->1 transition on an unmasked channel causes a corresponding bit in - * a 32-bit selector to be set. Each bit in the selector covers a 32-bit - * word in the PENDING or EXCEPTION bitfield array. + * To expedite scanning of pending notifications, any 0->1 pending + * transition on an unmasked channel causes a corresponding bit in a + * 32-bit selector to be set. Each bit in the selector covers a 32-bit + * word in the PENDING bitfield array. */ u32 evtchn_pending[32]; u32 evtchn_pending_sel; u32 evtchn_exception[32]; - u32 evtchn_exception_sel; u32 evtchn_mask[32]; /* diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index e471e56afd..3dd4cf383e 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -71,11 +71,8 @@ static inline void evtchn_set_pending(struct task_struct *p, int port) static inline void evtchn_set_exception(struct task_struct *p, int port) { - shared_info_t *s = p->shared_info; - if ( !test_and_set_bit(port, &s->evtchn_exception[0]) && - !test_bit (port, &s->evtchn_mask[0]) && - !test_and_set_bit(port>>5, &s->evtchn_exception_sel) ) - guest_notify(p); + if ( !test_and_set_bit(port, &p->shared_info->evtchn_exception[0]) ) + evtchn_set_pending(p, port); } /* diff --git a/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c b/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c index 8b76e8ab4e..222097f20d 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c @@ -143,8 +143,6 @@ void xen_console_init(void) } register_console(&kcons_info); - - evtchn_clear_error_virq(); } diff --git a/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c b/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c index faa1bb0b61..985d72821d 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c @@ -40,35 +40,25 @@ static unsigned int ring_cons, ring_prod, ring_overflow; static DECLARE_WAIT_QUEUE_HEAD(evtchn_wait); static struct fasync_struct *evtchn_async_queue; -/* - * Pending normal notifications and pending exceptional notifications. - * 'Pending' means that we received an upcall but this is not yet ack'ed - * from userspace by writing to /dev/xen/evtchn. - */ -static u32 pend_nrm[32], pend_exc[32]; +/* Which ports is user-space bound to? */ +static u32 bound_ports[32]; static spinlock_t lock; -void evtchn_device_upcall(int port, int exception) +void evtchn_device_upcall(int port) { u16 port_subtype; + shared_info_t *s = HYPERVISOR_shared_info; spin_lock(&lock); mask_evtchn(port); + clear_evtchn(port); - if ( likely(!exception) ) - { - clear_evtchn(port); - set_bit(port, &pend_nrm[0]); + if ( likely(!synch_test_and_clear_bit(port, &s->evtchn_exception[0])) ) port_subtype = PORT_NORMAL; - } else - { - clear_evtchn_exception(port); - set_bit(port, &pend_exc[0]); port_subtype = PORT_EXCEPTION; - } if ( ring != NULL ) { @@ -92,28 +82,8 @@ void evtchn_device_upcall(int port, int exception) static void __evtchn_reset_buffer_ring(void) { - u32 m; - unsigned int i, j; - - /* Initialise the ring with currently outstanding notifications. */ + /* Initialise the ring to empty. Clear errors. */ ring_cons = ring_prod = ring_overflow = 0; - - for ( i = 0; i < 32; i++ ) - { - m = pend_exc[i]; - while ( (j = ffs(m)) != 0 ) - { - m &= ~(1 << --j); - ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_EXCEPTION); - } - - m = pend_nrm[i]; - while ( (j = ffs(m)) != 0 ) - { - m &= ~(1 << --j); - ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_NORMAL); - } - } } static ssize_t evtchn_read(struct file *file, char *buf, @@ -232,11 +202,8 @@ static ssize_t evtchn_write(struct file *file, const char *buf, spin_lock_irq(&lock); for ( i = 0; i < (count/2); i++ ) - { - clear_bit(kbuf[i]&PORTIDX_MASK, - (kbuf[i]&PORT_EXCEPTION) ? &pend_exc[0] : &pend_nrm[0]); - unmask_evtchn(kbuf[i]&PORTIDX_MASK); - } + if ( test_bit(kbuf[i], &bound_ports[0]) ) + unmask_evtchn(kbuf[i]); spin_unlock_irq(&lock); rc = count; @@ -249,14 +216,35 @@ static ssize_t evtchn_write(struct file *file, const char *buf, static int evtchn_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - if ( cmd != EVTCHN_RESET ) - return -EINVAL; - + int rc = 0; + spin_lock_irq(&lock); - __evtchn_reset_buffer_ring(); + + switch ( cmd ) + { + case EVTCHN_RESET: + __evtchn_reset_buffer_ring(); + break; + case EVTCHN_BIND: + if ( !test_and_set_bit(arg, &bound_ports[0]) ) + unmask_evtchn(arg); + else + rc = -EINVAL; + break; + case EVTCHN_UNBIND: + if ( test_and_clear_bit(arg, &bound_ports[0]) ) + mask_evtchn(arg); + else + rc = -EINVAL; + break; + default: + rc = -ENOSYS; + break; + } + spin_unlock_irq(&lock); - return 0; + return rc; } static unsigned int evtchn_poll(struct file *file, poll_table *wait) @@ -298,12 +286,17 @@ static int evtchn_open(struct inode *inode, struct file *filp) static int evtchn_release(struct inode *inode, struct file *filp) { + int i; + spin_lock_irq(&lock); if ( ring != NULL ) { free_page((unsigned long)ring); ring = NULL; } + for ( i = 0; i < NR_EVENT_CHANNELS; i++ ) + if ( test_and_clear_bit(i, &bound_ports[0]) ) + mask_evtchn(i); spin_unlock_irq(&lock); evtchn_dev_inuse = 0; diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c index 4eb83c4b4c..fc3efb810e 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c @@ -38,76 +38,37 @@ static int irq_bindcount[NR_IRQS]; /* Upcall to generic IRQ layer. */ extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); -static void evtchn_handle_normal(shared_info_t *s, struct pt_regs *regs) -{ - unsigned long l1, l2; - unsigned int l1i, l2i, port; - int irq; - - l1 = xchg(&s->evtchn_pending_sel, 0); - while ( (l1i = ffs(l1)) != 0 ) - { - l1i--; - l1 &= ~(1 << l1i); - - l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]; - while ( (l2i = ffs(l2)) != 0 ) - { - l2i--; - l2 &= ~(1 << l2i); - - port = (l1i << 5) + l2i; - if ( (irq = evtchn_to_irq[port]) != -1 ) - do_IRQ(irq, regs); - else - evtchn_device_upcall(port, 0); - } - } -} - -static void evtchn_handle_exceptions(shared_info_t *s, struct pt_regs *regs) -{ - unsigned long l1, l2; - unsigned int l1i, l2i, port; - int irq; - - l1 = xchg(&s->evtchn_exception_sel, 0); - while ( (l1i = ffs(l1)) != 0 ) - { - l1i--; - l1 &= ~(1 << l1i); - - l2 = s->evtchn_exception[l1i] & ~s->evtchn_mask[l1i]; - while ( (l2i = ffs(l2)) != 0 ) - { - l2i--; - l2 &= ~(1 << l2i); - - port = (l1i << 5) + l2i; - if ( (irq = evtchn_to_irq[port]) != -1 ) - { - printk(KERN_ALERT "Error on IRQ line %d!\n", irq); - synch_clear_bit(port, &s->evtchn_exception[0]); - } - else - evtchn_device_upcall(port, 1); - } - } -} - void evtchn_do_upcall(struct pt_regs *regs) { - unsigned long flags; + unsigned long l1, l2; + unsigned int l1i, l2i, port; + int irq; + unsigned long flags; shared_info_t *s = HYPERVISOR_shared_info; local_irq_save(flags); while ( synch_test_and_clear_bit(0, &s->evtchn_upcall_pending) ) { - if ( s->evtchn_pending_sel != 0 ) - evtchn_handle_normal(s, regs); - if ( s->evtchn_exception_sel != 0 ) - evtchn_handle_exceptions(s, regs); + l1 = xchg(&s->evtchn_pending_sel, 0); + while ( (l1i = ffs(l1)) != 0 ) + { + l1i--; + l1 &= ~(1 << l1i); + + l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]; + while ( (l2i = ffs(l2)) != 0 ) + { + l2i--; + l2 &= ~(1 << l2i); + + port = (l1i << 5) + l2i; + if ( (irq = evtchn_to_irq[port]) != -1 ) + do_IRQ(irq, regs); + else + evtchn_device_upcall(port); + } + } } local_irq_restore(flags); @@ -346,16 +307,16 @@ static struct hw_interrupt_type pirq_type = { NULL }; -static void error_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void misdirect_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - printk(KERN_ALERT "unexpected VIRQ_ERROR trap to vector %d\n", irq); + /* nothing */ } -static struct irqaction error_action = { - error_interrupt, +static struct irqaction misdirect_action = { + misdirect_interrupt, SA_INTERRUPT, 0, - "error", + "misdirect", NULL, NULL }; @@ -372,7 +333,10 @@ void __init init_IRQ(void) /* No event-channel -> IRQ mappings. */ for ( i = 0; i < NR_EVENT_CHANNELS; i++ ) + { evtchn_to_irq[i] = -1; + mask_evtchn(i); /* No event channels are 'live' right now. */ + } /* No IRQ -> event-channel mappings. */ for ( i = 0; i < NR_IRQS; i++ ) @@ -400,5 +364,5 @@ void __init init_IRQ(void) irq_desc[pirq_to_irq(i)].handler = &pirq_type; } - (void)setup_irq(bind_virq_to_irq(VIRQ_ERROR), &error_action); + (void)setup_irq(bind_virq_to_irq(VIRQ_MISDIRECT), &misdirect_action); } diff --git a/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h b/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h index fd52b97009..8dbb460cda 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h +++ b/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h @@ -23,7 +23,7 @@ void evtchn_do_upcall(struct pt_regs *regs); /* Entry point for notifications into the userland character device. */ -void evtchn_device_upcall(int port, int exception); +void evtchn_device_upcall(int port); static inline void mask_evtchn(int port) { @@ -34,7 +34,6 @@ static inline void mask_evtchn(int port) static inline void unmask_evtchn(int port) { shared_info_t *s = HYPERVISOR_shared_info; - int need_upcall = 0; synch_clear_bit(port, &s->evtchn_mask[0]); @@ -42,19 +41,8 @@ static inline void unmask_evtchn(int port) * The following is basically the equivalent of 'hw_resend_irq'. Just like * a real IO-APIC we 'lose the interrupt edge' if the channel is masked. */ - - /* Asserted a standard notification? */ if ( synch_test_bit (port, &s->evtchn_pending[0]) && - !synch_test_and_set_bit(port>>5, &s->evtchn_pending_sel) ) - need_upcall = 1; - - /* Asserted an exceptional notification? */ - if ( synch_test_bit (port, &s->evtchn_exception[0]) && - !synch_test_and_set_bit(port>>5, &s->evtchn_exception_sel) ) - need_upcall = 1; - - /* If asserted either type of notification, check the master flags. */ - if ( need_upcall && + !synch_test_and_set_bit(port>>5, &s->evtchn_pending_sel) && !synch_test_and_set_bit(0, &s->evtchn_upcall_pending) && !synch_test_bit (0, &s->evtchn_upcall_mask) ) evtchn_do_upcall(NULL); @@ -72,16 +60,6 @@ static inline void clear_evtchn_exception(int port) synch_clear_bit(port, &s->evtchn_exception[0]); } -static inline void evtchn_clear_error_virq(void) -{ - /* - * XXX This prevents a bogus 'VIRQ_ERROR' when interrupts are enabled - * for the first time. This works because by this point all important - * VIRQs (eg. timer) have been properly bound. - */ - synch_clear_bit(0, &HYPERVISOR_shared_info->evtchn_pending[0]); -} - /* * CHARACTER-DEVICE DEFINITIONS */ @@ -95,6 +73,10 @@ static inline void evtchn_clear_error_virq(void) /* /dev/xen/evtchn ioctls: */ /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */ -#define EVTCHN_RESET _IO('E', 1) +#define EVTCHN_RESET _IO('E', 1) +/* EVTCHN_BIND: Bind to teh specified event-channel port. */ +#define EVTCHN_BIND _IO('E', 2) +/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */ +#define EVTCHN_UNBIND _IO('E', 3) #endif /* __ASM_EVTCHN_H__ */